#ifndef __MATH_TOOL_H__
#define __MATH_TOOL_H__
#include <type_traits>
#include <numeric>
#include <cmath>

struct Constant {
    static constexpr float Pi    = 3.14159265358979323846f;
    static constexpr float InvPi = 0.31830988618379067154f;
    static constexpr float Epsilon = std::numeric_limits<float>::epsilon();
};

constexpr inline float radians(float deg) {
    return deg * Constant::Pi / 180.0f;
}

constexpr inline float degree(float rad) {
    return rad * 180.0f / Constant::Pi;
}

template<class T>
typename std::enable_if<!std::numeric_limits<T>::is_integer, bool>::type
almost_equal(T x, T y, int ulp = 2)
{
    return std::abs(x-y) <= std::numeric_limits<T>::epsilon() * std::abs(x+y) * ulp
           || std::abs(x-y) < std::numeric_limits<T>::min();
}

template <class T, class U>
auto lerp(const T& p1, const T& p2, U t) noexcept
-> std::common_type_t<T, U>
{
    return p1 + (p2 - p1) * t;
}

inline float clamp(float min, float max, float t) {
    if (t > max) {
        t = max;
    }
    if (t < min) {
        t = min;
    }
    return t;
}

#endif